package org.ISCS.controller;

import org.ISCS.entity.*;
import org.ISCS.entity.customize.CustomResult;
import org.ISCS.entity.version.ServiceInfo;
import org.ISCS.entity.webhook.Webhook;
import org.ISCS.service.*;
import org.ISCS.service.buildimpl.DockerHubService;
import org.ISCS.service.buildimpl.DockerService;
import org.ISCS.service.utilimpl.FileService;
import org.ISCS.service.utilimpl.KubernetesService;
import org.ISCS.service.utilimpl.ReadDependencyService;
import org.ISCS.service.utilimpl.ServiceReaderService;
import org.ISCS.utils.MavenPackager;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/detect")
public class MainController {
    @Autowired
    ProjectService projectService;

    @Autowired
    ServiceReaderService serviceReaderService;

    @Autowired
    ServiceService serviceService;

    @Autowired
    DependencyService dependencyService;

    @Autowired
    ReadDependencyService readDependencyService;

    @Autowired
    FileService fileService;

    @Autowired
    DockerfileService dockerfileService;

    @Autowired
    DockerService dockerService;

    @Autowired
    DockerimageService dockerimageService;

    @Autowired
    DockerhubService dockerhubService;

    @Autowired
    K8sinfoService k8sinfoService;

    @Autowired
    KubernetesService kubernetesService;

    @PostMapping("/handleWebhooks")
    public CustomResult toHandleWebhooks(@RequestBody Webhook webhook) throws IOException, InterruptedException {
        /*
         * 1. 拉取代码 接收到请求拉取对应代码
         * */
        String remoteName = webhook.getRepository().getName();
        String remoteUrl = webhook.getRepository().getUrl();
        String projectPath = "/mj/" + remoteName;
        String filePath = projectPath + "/project.json";
        String create_user = webhook.getHead_commit().getCommitter().getUser_name();
        System.out.println(remoteUrl);
        try {
            // 如果文件夹存在且不为空，我就删除它
            File directory = new File(projectPath);
            if (directory.exists() && directory.isDirectory()) {
                String[] files = directory.list();
                if (files != null && files.length > 0) {
                    try {
                        FileUtils.deleteDirectory(directory);
                        System.out.println("Directory deleted successfully");
                    } catch (IOException e) {
                        e.printStackTrace();
                        System.out.println("Failed to delete directory");
                    }
                }
            }
            // Git拉取项目
            Git.cloneRepository()
                    .setURI(remoteUrl)
                    .setDirectory(new File("/mj/" + remoteName))
                    .setCredentialsProvider(new UsernamePasswordCredentialsProvider("3056847915@qq.com", "zmzzmz010627"))
                    .call();
        } catch (GitAPIException e) {
            e.printStackTrace();
        }
        // 项目处理
        // 查找对应项目的service信息
        List<ServiceInfo> serviceInfoList = serviceReaderService.readServicesFromJsonFile(filePath);
        int serversNum = serviceInfoList.size();
        // 设置需要进行构建操作的servicesList
        List<Services> operateServicesList = null;
        // 根据项目名查找是否项目已存在
        CustomResult rs_project = projectService.getProjectByName(remoteName);
        if (rs_project.getData() == null) {
            // 如果没有没有找到对应的项目 则添加一条project数据至数据库
            Project newproject = new Project(remoteName, serversNum, remoteUrl, create_user, new Date());
            projectService.insertProject(newproject);
            // 创建项目之后就要创建对应的服务
            Project p1 = (Project) projectService.getProjectByName(remoteName).getData();
            Long p1_id = p1.getId();
            Collection<Services> servicesList = new ArrayList<>();
            for (ServiceInfo serviceInfo : serviceInfoList) {
                Services service = new Services();
                service.setServiceName(serviceInfo.getName());
                service.setServiceVersion(serviceInfo.getVersion());
                service.setAffiliateProjectId(p1_id);
                service.setInstanceNum(1);
                service.setVisitTimes(0);
                servicesList.add(service);
            }
            // 查找所有服务添加进操作列表
            System.out.println("p1_id：" + p1_id);
            serviceService.insertByList(servicesList);
            List<Services> servicesListNew = (List<Services>) serviceService.getServicesByProjectId(p1_id).getData();
            operateServicesList = servicesListNew;
        } else {
            // 否则就是已经存在对应的项目了
            // 判断服务是否有增减
            // 获取此项目下的服务
            Project p2 = (Project) projectService.getProjectByName(remoteName).getData();
            Long p2_id = p2.getId();
            List<Services> servicesList = (List<Services>) serviceService.getServicesByProjectId(p2_id).getData();
            // 进行比对操作
            Set<String> serviceSet = servicesList.stream()
                    .map(s -> s.getServiceName() + s.getServiceVersion())
                    .collect(Collectors.toSet());

            for (ServiceInfo info : serviceInfoList) {
                String combined = info.getName() + info.getVersion();
                if (!serviceSet.contains(combined)) {
                    Services newService = new Services();
                    newService.setServiceName(info.getName());
                    newService.setServiceVersion(info.getVersion());
                    newService.setAffiliateProjectId(p2_id);
                    newService.setInstanceNum(1);
                    newService.setVisitTimes(0);
                    // 添加至操作列表
                    operateServicesList.add(serviceService.insertService(newService));
                }
            }
        }
        if (operateServicesList != null){
            for (Services services : operateServicesList) {
                String version = services.getServiceVersion();
                /*
                 * 2. 进行相应的依赖分析
                 * */
                // 2.1 新增依赖情况
                Dependency dependency = new Dependency();
                dependency.setDependencyStatus(0); // 0表示解析中
                dependency.setAffiliateServiceId(services.getId());
                dependency.setDependencyCreateTime(new Date());
                dependencyService.insert(dependency);
                // 2.2 打包zip 分析依赖(获取具体项目下的依赖json文件)
                // 读取目标文件 url = "file:" +  projectPath + service.getName + "dependency.json"

                // 2.3 根据结果 更新依赖信息(sleep3秒)
                // Thread.sleep(3000);
                String dependencyUrl = projectPath + "/" + services.getServiceName() + "/dependency.json";
                String dependencyData =  readDependencyService.readDependencyData(dependency, dependencyUrl);
                dependency.setDependencyData(dependencyData);
                dependency.setDependencyStatus(1); // 表示解析完成
                dependencyService.updateDependencyById(dependency);
                /*
                 * 3. 生成Dockerfile
                 * */
                // 3.1 新增dockerfile情况
                Dockerfile dockerfile = new Dockerfile();
                dockerfile.setAffiliateServiceId(services.getId());
                dockerfile.setDockerfileStatus(0); // 0表示生成中
                dockerfileService.insertDockerFile(dockerfile);
                // 3.2 生成Dockerfile，获取对应dockerfile内容
                // 3.3 更新dockerfile信息
//            Thread.sleep(3000);

                String dockerfileUrl = projectPath + "/" + services.getServiceName() + "/Dockerfile";
                System.out.println("dockerfileUrl：" + dockerfileUrl);
                String dockerfileData = fileService.readDockerfile(dockerfileUrl);
                dockerfile.setDockerfileCreateTime(new Date());
                dockerfile.setDockerfileData(dockerfileData);
                dockerfile.setDockerfileStatus(1);
                dockerfileService.updateDockerFileById(dockerfile);
                /*
                 * 4. 打包成docker镜像
                 * */
                // 4.1 新增成docker情况
                Dockerimage dockerimage = new Dockerimage();
                String imageName ="registry.cn-hangzhou.aliyuncs.com/fremount/" + services.getServiceName() + ":v" + services.getServiceVersion();
//                String dockerImageUrl = "https://hub.docker.com/layers/fremount/" + services.getServiceName() + "/test" + services.getServiceVersion();
                System.out.println("imageName: " +imageName);
                String dockerImageUrl = "registry-vpc.cn-hangzhou.aliyuncs.com/fremount/"+services.getServiceName();
                // 如果有pom则进行java打包操作
                MavenPackager mavenPackager = new MavenPackager();
                mavenPackager.packageService(projectPath,services.getServiceName());

                dockerimage.setDockerImageStatus(0); //  0 表示正在构建中
                dockerimage.setDockerImageName(imageName);
                dockerimage.setAffiliateServiceId(services.getId());
                dockerimage.setDockerImageUrl(dockerImageUrl);
                dockerimageService.insertDockerImage(dockerimage);
                // 4.2 根据log获取docker镜像相关信息
                dockerService.buildDockerImage(dockerfileUrl, dockerimage, imageName);
//            Thread.sleep(3000);
                dockerimage.setDockerImageCreateTime(new Date());
                // 4.3 更新docker镜像信息
                dockerimageService.updateDockerImage(dockerimage);
                /*
                 * 5. 上传dockerhub
                 * */
            // 5.1 新增dockerhub情况
            Dockerhub dockerHub = new Dockerhub();
            dockerHub.setAffiliateDockerId(dockerimage.getId());
            dockerHub.setDockerhubStatus(0); // 0 表示正在上传中
            dockerHub.setDockerhubName(imageName);
            dockerhubService.insertDockerHubInfo(dockerHub);
            // 5.2 根据log获取docker镜像相关信息
            DockerHubService dockerHubService = new DockerHubService();
            dockerHubService.pushDockerImage(imageName, dockerHub);
//            Thread.sleep(3000);
            // 5.3 更新docker镜像信息
            dockerHub.setDockerhubTime(new Date());
            dockerhubService.updateDockerHubInfo(dockerHub);
                // 6. 部署至k8s
                // 6.1 新增k8s情况
            K8sinfo k8sinfo = new K8sinfo();
            k8sinfo.setPodStatus(0); // 表示正在构建中
            k8sinfo.setDeployStatus(0); // 表示正在构建中
            k8sinfo.setServiceStatus(0); // 表示正在构建中
            String newVersion = version.replace(".", "");
            k8sinfo.setPodName(services.getServiceName() + "-pod-v" + newVersion);
            k8sinfo.setDeployName(services.getServiceName() + "-deploy-v" + newVersion);
            k8sinfo.setServiceName(services.getServiceName() + "-service-v" + newVersion);
            k8sinfo.setAffilateServiceId(services.getId());
            k8sinfoService.insertK8sInfo(k8sinfo);
            String yamlUrl = projectPath + "/" + services.getServiceName() + "/k8s.yaml";
            // 6.2 根据log获取k8s相关信息
            kubernetesService.applyKubernetesYaml(yamlUrl);
            // 6.3 更新k8s信息 这一步有待考究
            k8sinfo.setPodStatus(1); // 表示构建完成
            k8sinfo.setDeployStatus(1); // 表示构建完成
            k8sinfo.setServiceStatus(1); // 表示构建完成
            k8sinfoService.updateK8sInfo(k8sinfo);
            }
        }
        return CustomResult.ok();
    }
}
